package com.holystone.splunk.app.service.impl;

import com.holystone.splunk.app.service.ISplunkIndexService;
import com.holystone.splunk.common.SystemConstant;
import com.holystone.splunk.utils.DateFormatUtils;
import com.holystone.splunk.utils.JSONUtils;
import com.holystone.splunk.utils.StringUtils;
import com.splunk.*;
import org.apache.log4j.Logger;
import org.codehaus.jackson.JsonNode;
import org.springframework.stereotype.Service;

import java.io.*;
import java.net.Socket;
import java.util.*;

/**
 * Copyright (c) 2017, HOLYSTONE Technologies, Inc.
 * All right reserved.
 *
 * @author huyan
 * @date 2017/12/1
 * @desc:
 */
@Service(value = "splunkIndexService")
public class SplunkIndexServiceImpl extends SplunkBaseServiceImpl implements ISplunkIndexService {

    private Logger logger = Logger.getLogger(this.getClass());

    @Override
    public Index createNewIndex(String indexName) {
        logger.debug(">>>>> 创建一个新的index createNewIndex() indexName:" + indexName);
        Index index = getService().getIndexes().create(indexName);
        logger.debug("<<<<< 创建一个新的index createNewIndex() indexName:" + indexName);
        return index;
    }

    @Override
    public Index getIndexByName(String indexName) {
        logger.debug(">>>>> 通过名称获取index getIndexByName() indexName:" + indexName);
        Index index = getService().getIndexes().get(indexName);
        logger.debug("<<<<< 通过名称获取index getIndexByName() indexName:" + indexName);
        return index;
    }

    @Override
    public void insertData2Index(String indexName, String sourcetype, String insertData) throws IOException {
        logger.debug(">>>>> 向index中插入数据 insertData2Index() indexName:" + indexName + " sourcetype:" + sourcetype);
        Index index = getIndexByName(indexName);
        Args args = new Args();
        args.put("sourcetype", sourcetype);
        /**
         * 两种插入方式（可看sdk）
         * 1.快速插入：submit/ 量小，单个插入
         * 2.安全插入：attach/ 量大，批量插入
         */
        //1.
        //index.submit(args, insertData);
        //2.
        Socket socket = index.attach(args);
        try {
            OutputStream os = socket.getOutputStream();
            Writer writer = new OutputStreamWriter(os, "UTF-8");
            writer.write(insertData);
            writer.flush();
        } finally {
            socket.close();
        }
        logger.debug("<<<<< 向index中插入数据 insertData2Index() indexName:" + indexName + " sourcetype:" + sourcetype);
    }

    @Override
    public Integer deleteDataFromIndex(String sourcetype, Object value) throws IOException {
        logger.debug(">>>>> 删除数据 deleteDataFromIndex()");
        // 封装查询
        String query = "search index=" + SystemConstant.SPLUNK_INDEX +
                " sourcetype=" + sourcetype +
                " " + value +
                " | delete";
        // 查询
        JsonNode result = search(query, null, null, null, null);
        // 封装返回结果
        if (result == null) {
            return 0;
        }
        if (result.isArray()) {
            for (int i = 0; i < result.size(); i++) {
                JsonNode jsonNode = result.get(i);
                Iterator<String> nameIt = jsonNode.getFieldNames();
                while (nameIt.hasNext()) {
                    String name = nameIt.next();
                    if ("index".equals(name) && SystemConstant.SPLUNK_INDEX.equals(jsonNode.get("index").asText())) {
                        return jsonNode.get("deleted").asInt(0);
                    }
                }
            }
        }
        logger.debug("<<<<< 删除数据 deleteDataFromIndex()");
        return 0;
    }

    @Override
    public JsonNode search(String query, Integer pageNo, Integer pageSize, Date earliest, Date latest) throws IOException {
        logger.debug(">>>>> 搜索 search()");
        // 查询条件
        JobResultsArgs args = new JobResultsArgs();
        args.setOutputMode(JobResultsArgs.OutputMode.JSON);
        if (earliest != null) {
            args.put("earliest_time", DateFormatUtils.javaDate2CDate(earliest));
        }
        if (latest != null) {
            args.put("latest_time", DateFormatUtils.javaDate2CDate(latest));
        }
        if (pageNo != null) {
            int offset = (pageNo - 1) * pageSize;
            args.setOffset(offset);
        }
        if (pageSize != null) {
            args.setCount(pageSize);
        }
        InputStream is = getService().oneshotSearch(query, args);
        logger.debug(">>>>> 搜索 "+query);
        logger.debug(">>>>> 搜索 search() 1");
        String data=StringUtils.inputStream2String(is);
        logger.debug(">>>>> 搜索 search() 2");
        JsonNode jsonNode = JSONUtils.jsonStr2JsonNode(data);
        logger.debug(">>>>> 搜索 search() 3");
        if (jsonNode != null) {
            return jsonNode.get("results");
        }
        logger.debug("<<<<< 搜索 search()");
        return null;
    }

    @Override
    public List<JsonNode> getResultsFormSearch(String query, Date earliest, Date latest) throws IOException {
        logger.debug(">>>>> 获取results数据 getResultsFormSearch()");
        // 查询
        JsonNode results = search(query, null, null, earliest, latest);
        // 封装返回数据
        List<JsonNode> resultsList = new ArrayList<>();
        if (results != null && results.size() != 0) {
            if (results.isArray()) {
                for (int i = 0; i < results.size(); i++) {
                    resultsList.add(results.get(i));
                }
            }else {
                resultsList.add(results);
            }
        }
        logger.debug("<<<<< 获取results数据 getResultsFormSearch()");
        return resultsList;
    }

    @Override
    public List<JsonNode> getDataFromIndex(String query, Integer pageNo, Integer pageSize, Date earliest, Date latest) throws IOException {
        logger.debug(">>>>> 从index中获取数据 getDataFromIndex()");
        // 查询
        JsonNode results = search(query, pageNo, pageSize, earliest, latest);
        // 封装返回结果
        List<JsonNode> jsonList = new ArrayList<>();
        if (results != null && results.size() != 0) {
            if (results.isArray()) {
                for (int i = 0, len = results.size(); i < len; i++) {
                    JsonNode json = results.get(i).get("_raw");
                    jsonList.add(json);
                }
            } else if (!results.isArray()) {
                JsonNode json = results.get("_raw");
                jsonList.add(json);
            }
        }
        logger.debug("<<<<< 从index中获取数据 getDataFromIndex()");
        return jsonList;
    }

    @Override
    public List<String> getDIYStatisticaData(String indexName, String sourcetype, String statisName) throws IOException {
        logger.debug(">>>>> 获取自定义统计数据 getDIYStatisticaData() name:" + statisName);
        // 封装query
        String query = "search index=" + indexName +
                " sourcetype=" + sourcetype +
                " |transaction " + statisName +
                " |table " + statisName;

        JsonNode results = search(query, null, null, null, null);
        // 封装结果
        List<String> nameList = new ArrayList<>();
        if (results != null && results.size() != 0) {
            if (results.isArray()) {
                for (int i = 0, len = results.size(); i < len; i++) {
                    String name = results.get(i).get(statisName).asText();
                    nameList.add(name);
                }
            } else if (!results.isArray()) {
                String name = results.get(statisName).asText();
                nameList.add(name);
            }
        }
        logger.debug("<<<<< 获取自定义统计数据 getDIYStatisticaData() name:" + statisName);
        return nameList;
    }

    @Override
    public Integer getDIYTotalCount(String query, String statisName, Date earliest, Date latest) throws IOException {
        logger.debug(">>>>> 获取自定义统计总数 getDIYTotalCount()");
        JsonNode results = search(query, null, null, earliest, latest);
        if (results != null) {
            if (results.isArray()) {
                return results.get(0).get(statisName).asInt(0);
            }else {
                return results.get(statisName).asInt(0);
            }
        }
        logger.debug("<<<<< 获取自定义统计总数 getDIYTotalCount()");
        return 0;
    }

    @Override
    public String getEnddate(String query, String statisName) throws IOException {
        JsonNode results = search(query, null, null, null, null);
        if (results != null) {
            if (results.isArray()) {
                return results.get(0).get(statisName).asText();
            }else {
                return results.get(statisName).asText();
            }
        }
        logger.debug("<<<<< 获取自定义统计总数 getDIYTotalCount()");
        return "";
    }
}
